<html><head><meta charset="utf-8"><title>14 Webpack Dev Server 本地开发服务-慕课专栏</title>
			<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1">
			<meta name="renderer" content="webkit">
			<meta property="qc:admins" content="77103107776157736375">
			<meta property="wb:webmaster" content="c4f857219bfae3cb">
			<meta http-equiv="Access-Control-Allow-Origin" content="*">
			<meta http-equiv="Cache-Control" content="no-transform ">
			<meta http-equiv="Cache-Control" content="no-siteapp">
			<link rel="apple-touch-icon" sizes="76x76" href="https://www.imooc.com/static/img/common/touch-icon-ipad.png">
			<link rel="apple-touch-icon" sizes="120x120" href="https://www.imooc.com/static/img/common/touch-icon-iphone-retina.png">
			<link rel="apple-touch-icon" sizes="152x152" href="https://www.imooc.com/static/img/common/touch-icon-ipad-retina.png">
			<link href="https://moco.imooc.com/captcha/style/captcha.min.css" rel="stylesheet">
			<link rel="stylesheet" href="https://www.imooc.com/static/moco/v1.0/dist/css/moco.min.css?t=201907021539" type="text/css">
			<link rel="stylesheet" href="https://www.imooc.com/static/lib/swiper/swiper-3.4.2.min.css?t=201907021539">
			<link rel="stylesheet" href="https://static.mukewang.com/static/css/??base.css,common/common-less.css?t=2.5,column/zhuanlanChapter-less.css?t=2.5,course/inc/course_tipoff-less.css?t=2.5?v=201907051055" type="text/css">
			<link charset="utf-8" rel="stylesheet" href="https://www.imooc.com/static/lib/ueditor/themes/imooc/css/ueditor.css?v=201907021539"><link rel="stylesheet" href="https://www.imooc.com/static/lib/baiduShare/api/css/share_style0_16.css?v=6aba13f0.css"></head>
			<body><div id="main">

<div class="container clearfix" id="top" style="display: block; width: 1134px;">
    
    <div class="center_con js-center_con l" style="width: 1134px;">
        <div class="article-con">
                            <!-- 买过的阅读 -->
                <div class="map">
                    <a href="/read" target="_blank"><i class="imv2-feather-o"></i></a>
                    <a href="/read/29" target="_blank">Webpack 从零入门到工程化实战</a>
                    <a href="" target="_blank">
                        <span>
                            / 2-8 14 Webpack Dev Server 本地开发服务
                        </span>
                    </a>
                </div>

            


            <div class="art-title" style="margin-top: 0px;">
                14 Webpack Dev Server 本地开发服务
            </div>
            <div class="art-info">
                
                <span>
                    更新时间：2019-06-24 09:27:11
                </span>
            </div>
            <div class="art-top">
                                <img src="https://img.mukewang.com/5cd963ac0001b6ac06400359.jpg" alt="">
                                                <div class="famous-word-box">
                    <img src="https://www.imooc.com/static/img/column/bg-l.png" alt="" class="bg1 bg">
                    <img src="https://www.imooc.com/static/img/column/bg-r.png" alt="" class="bg2 bg">
                    <div class="famous-word">不想当将军的士兵，不是好士兵。<p class="author">——拿破仑</p></div>
                </div>
                            </div>
            <div class="art-content js-lookimg">
                <div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;"><a href="https://github.com/webpack/webpack-dev-server">webpack-dev-server</a>是一个基于 <a href="https://expressjs.com/">Express</a> 的本地开发服务器（看 Roadmap 下个版本内核会从 Express 切换到 Koa）。它使用 <a href="https://github.com/webpack/webpack-dev-middleware">webpack-dev-middleware</a> 中间件来为通过 Webpack 打包生成的资源文件提供 Web 服务。它还有一个通过 Socket IO 连接着 webpack-dev-server 服务器的小型运行时程序。webpack-dev-server 发送关于编译状态的消息到客户端，客户端根据消息作出响应。</p>
</div><div class="cl-preview-section"><blockquote>
<p style="font-size: 20px; line-height: 38px;">Tips：简单来说 webpack-dev-server 就是一个 Express 的小型服务器，它是通过 Express 的<a href="https://expressjs.com/zh-cn/guide/using-middleware.html">中间件</a> <a href="https://github.com/webpack/webpack-dev-middleware">webpack-dev-middleware</a>和 Webpack 进行交互的。所以我们如果自己的项目本身就是个 Express 服务器，那么可以使用 webpack-dev-middleware 和 <a href="https://github.com/webpack-contrib/webpack-hot-middleware">webpack-hot-middleware</a> 两个中间件来实现 HMR 功能。关于 webpack-dev-middleware 和 webpack-hot-middleware 中间件来实现 webpack-dev-server 的内容，在后续章节还会有介绍。</p>
</blockquote>
</div><div class="cl-preview-section"><h2 id="命令行" style="font-size: 30px;">命令行</h2>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">webpack-dev-server 安装之后，会提供一个 bin 命令行，通过命令行可以启动对应的服务。</p>
</div><div class="cl-preview-section"><pre class="  language-bash"><code class="prism  language-bash"><span class="token comment"># 项目中安装 webpack-dev-server</span>
<span class="token function">npm</span> i webpack-dev-server
<span class="token comment"># 使用 npx 启动</span>
npx webpack-dev-server
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">执行<code>webpack-dev-server</code>命令之后，它会读取 Webpack 的配置文件（默认是 webpack.config.js）然后将文件打包到内存中（所以看不到<code>dist</code>文件夹的生产，Webpack 会打包到硬盘上），这时候打开 server 的默认地址：<code>localhost:8080</code>就可以看到文件目录或者页面（默认是显示 index.html，没有则显示目录）。</p>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">跟<code>webpack-cli</code>一样，<code>webpack-dev-server</code>也有一些选项可以添加：</p>
</div><div class="cl-preview-section"><pre class="  language-bash"><code class="prism  language-bash"><span class="token comment"># 修改端口号和 host</span>
webpack-dev-server --port 3000 --host 127.0.0.1
<span class="token comment"># 启动inline 模式的自动刷新</span>
webpack-dev-server --hot --inline
<span class="token comment"># 手动指定 webpack config 文件</span>
webpack-dev-server --config webpack.xxx.js
<span class="token comment"># 指定 webpack 的 mode</span>
webpack-dev-server --mode development
<span class="token comment"># watch 功能，文件发生变化则触发重新编译</span>
webpack-dev-server --watch
<span class="token comment"># dev-server默认会将工作目录（当前目录）最为基本目录，可以手动修改它</span>
webpack-dev-server --content-base ./build
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">上面只介绍了常用的并且比较重要的一些命令行选项，要查看全部，可以使用<code>webpack-dev-server -h</code>查看帮助。</p>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">我们还可以将<code>webpack-dev-server</code>放到<code>package.json</code>的<code>scripts</code>里面，例如下面例子，执行<code>npm run dev</code>实际就是执行的对应<code>webpack-dev-server</code>命令：</p>
</div><div class="cl-preview-section"><pre class="  language-json"><code class="prism  language-json"><span class="token punctuation">{</span>
    <span class="token string">"scripts"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
        <span class="token string">"dev"</span><span class="token punctuation">:</span> <span class="token string">"webpack-dev-server --mode development --config webpack.config.dev.js --hot --inline --port 3000"</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
</div><div class="cl-preview-section"><h3 id="自动刷新">自动刷新</h3>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">在开发中，我们希望边写代码，边看到代码的执行情况，webpack-dev-server 提供自动刷新页面的功能可以满足我们的需求。webpack-dev-server 支持两种模式的自动刷新页面。</p>
</div><div class="cl-preview-section"><ul>
<li style="font-size: 20px; line-height: 38px;">iframe 模式：页面被放到一个 iframe 内，当发生变化时，会重新加载；</li>
<li style="font-size: 20px; line-height: 38px;">inline 模式：将 webpack-dev-server 的重载代码添加到产出的 bundle 中。</li>
</ul>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">两种模式都支持模块热替换（Hot Module Replacement）。模块热替换的好处是只替换更新的部分，而不是整个页面都重新加载。</p>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">使用方式：<code>webpack-dev-server --hot --inline</code>是开启<code>inline</code>模式的自动刷新。</p>
</div><div class="cl-preview-section"><h2 id="和-webpack-配置结合" style="font-size: 30px;">和 Webpack 配置结合</h2>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">webpack-dev-server 被 Webpack 作为内置插件对外提供了，这样可以直接在对应的 Webpack 配置文件中通过<code>devServer</code>这个属性的配置来配置自己的<code>webpack-dev-server</code>。</p>
</div><div class="cl-preview-section"><pre class="  language-js"><code class="prism  language-js"><span class="token keyword">const</span> path <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token comment">//...</span>
    devServer<span class="token punctuation">:</span> <span class="token punctuation">{</span>
        contentBase<span class="token punctuation">:</span> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'dist'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        port<span class="token punctuation">:</span> <span class="token number">9000</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">其中 <code>devServer.port</code> 表示服务器的监听端口，即运行后我们可以通过 <code>http://localhost:9000</code> 来访问应用；而 <code>devServer.contentBase</code> 表示服务器将从哪个目录去查找内容文件（即页面文件，比如 HTML）。</p>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">配置完之后，在项目中执行<code>webpack-dev-server</code>就可以看到命令行控制台有输出：</p>
</div><div class="cl-preview-section"><pre class="  language-log"><code class="prism  language-log">｢wds｣: Project is running at http://localhost:9000/
｢wds｣: webpack output is served from /
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">我们可以用<a href="http://localhost:9000/">http://localhost:9000/</a>这个地址来访问本地开发服务了。</p>
</div><div class="cl-preview-section"><blockquote>
<p style="font-size: 20px; line-height: 38px;">Tips：</p>
<ol>
<li style="font-size: 20px; line-height: 38px;">启动 devserver 是通过<code>webpack-dev-server</code>命令行来启动的，不是<code>webpack</code>命令，执行<code>webpack</code>时<code>devServer</code>内容会被忽略</li>
<li style="font-size: 20px; line-height: 38px;">在使用数组导出配置的方式时，只会使用第一个配置中的 <code>devServer</code> 选项，并将其用于数组中的其他所有配置。</li>
</ol>
</blockquote>
</div><div class="cl-preview-section"><h2 id="hot-module-replacement" style="font-size: 30px;">Hot Module Replacement</h2>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">HMR 即模块热替换（Hot Module Replacement）的简称，它可以在应用运行的时候，<strong>不需要刷新页面</strong>，就可以直接替换、增删模块。</p>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">Webpack 可以通过配置 <code>webpack.HotModuleReplacementPlugin</code> 插件来开启全局的 HMR 能力，开启后 <code>bundle</code> 文件会变大一些，因为它加入了一个小型的 HMR 运行时（runtime），当你的应用在运行的时候，Webpack 监听到文件变更并重新打包模块时，HMR 会判断这些模块是否接受 update，若允许，则发信号通知应用进行热替换。</p>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">要开启 HMR 功能，需要三步：</p>
</div><div class="cl-preview-section"><ol>
<li style="font-size: 20px; line-height: 38px;">设置<code>devServer.hot=true</code>，<code>devServer.inline=true</code>（默认）；
<ul>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.hot=true</code>：会给 entry 添加<code>webpack/hot/dev-serve</code>或者<code>webpack/hot/only-dev-serve</code>（<code>devServer.hotOnly=true</code>），这个是实现 HMR 的服务端代码；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.inline=true</code>：会给 entry 添加<code>webpack-dev-server/client</code>，这是通信客户端；</li>
</ul>
</li>
<li style="font-size: 20px; line-height: 38px;">在<code>webpack.config.js</code>中添加 plugins：<code>new webpack.HotModuleReplacementPlugin()</code>；</li>
<li style="font-size: 20px; line-height: 38px;">修改入口文件添加 HMR 支持代码：</li>
</ol>
</div><div class="cl-preview-section"><pre class="  language-js"><code class="prism  language-js"><span class="token comment">// 在入口文件index.js最后添加如下代码</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>module<span class="token punctuation">.</span>hot<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 通知 webpack 该模块接受 hmr</span>
    module<span class="token punctuation">.</span>hot<span class="token punctuation">.</span><span class="token function">accept</span><span class="token punctuation">(</span>err <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            console<span class="token punctuation">.</span><span class="token function">error</span><span class="token punctuation">(</span><span class="token string">'Cannot apply HMR update.'</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">最终修改后的<code>webpack.config.js</code>内容如下：</p>
</div><div class="cl-preview-section"><pre class="  language-js"><code class="prism  language-js"><span class="token keyword">const</span> path <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
    entry<span class="token punctuation">:</span> <span class="token string">'./src/index.js'</span><span class="token punctuation">,</span>
    devServer<span class="token punctuation">:</span> <span class="token punctuation">{</span>
        contentBase<span class="token punctuation">:</span> path<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'dist'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        port<span class="token punctuation">:</span> <span class="token number">9000</span><span class="token punctuation">,</span>
        <span class="token comment">// 开启 hmr 支持</span>
        hot<span class="token punctuation">:</span> <span class="token boolean">true</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    plugins<span class="token punctuation">:</span> <span class="token punctuation">[</span>
        <span class="token comment">// 添加 hmr plugin</span>
        <span class="token keyword">new</span> <span class="token class-name">webpack<span class="token punctuation">.</span>HotModuleReplacementPlugin</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">经过上面配置之后，再次执行<code>webpack-dev-server</code>，打开<code>http://localhost:9000</code>，然后修改<code>index.js</code>内容，就能看到效果了</p>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;"><img src="http://img.mukewang.com/5cf46ee100011e5c00020024.gif" alt="图片描述" data-original="http://img.mukewang.com/5cf46ee100011e5c00020024.gif" class="" style="cursor: pointer;"></p>
</div><div class="cl-preview-section"><blockquote>
<p style="font-size: 20px; line-height: 38px;">Tips：使用 webpack-dev-server 的 CLI 功能只需要命令行中添加<code>--hot</code>，webpack-dev-server 会自动将<code>webpack.HotModuleReplacementPlugin</code>这个插件添加到 Webpack 的配置中去，所以开启 HotModuleReplacementPlugin 最简单的方式就是使用 inline 模式（命令行添加<code>--inline</code>）。</p>
</blockquote>
</div><div class="cl-preview-section"><h2 id="proxy" style="font-size: 30px;">proxy</h2>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">在实际开发中，本地开发服务器是不能直接请求线上数据接口的，这是因为浏览器的同源安全策略导致的跨域问题，我们可以使用<code>devServer.proxy</code>来解决本地开发跨域的问题。</p>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">下面的配置是将页面访问的<code>/api</code>所有请求都转发到了<code>baidu.com</code>上：</p>
</div><div class="cl-preview-section"><pre class="  language-js"><code class="prism  language-js">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token comment">//...</span>
    devServer<span class="token punctuation">:</span> <span class="token punctuation">{</span>
        proxy<span class="token punctuation">:</span> <span class="token punctuation">{</span>
            <span class="token string">'/api'</span><span class="token punctuation">:</span> <span class="token string">'http://baidu.com'</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">那么，我们请求<code>/api/users</code>则会被转发到<code>http://baidu.com/api/users</code>线上地址。</p>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;"><code>devServer.proxy</code>的值还支持高级属性，通过高级属性我们可以做更多的事情，如上面的需求变成，将<code>/api/users</code>转发到<code>http://baidu.com/users</code>，那么配置就需要改成：</p>
</div><div class="cl-preview-section"><pre class="  language-js"><code class="prism  language-js">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token comment">//...</span>
    devServer<span class="token punctuation">:</span> <span class="token punctuation">{</span>
        proxy<span class="token punctuation">:</span> <span class="token punctuation">{</span>
            <span class="token string">'/api'</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
                target<span class="token punctuation">:</span> <span class="token string">'http://baidu.com'</span><span class="token punctuation">,</span>
                pathRewrite<span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token string">'^/api'</span><span class="token punctuation">:</span> <span class="token string">''</span><span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">如果我们需要转发的网站是支持 https 的，那么需要增加<code>secure=false</code>，来防止转发失败：</p>
</div><div class="cl-preview-section"><pre class="  language-js"><code class="prism  language-js">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token comment">//...</span>
    devServer<span class="token punctuation">:</span> <span class="token punctuation">{</span>
        proxy<span class="token punctuation">:</span> <span class="token punctuation">{</span>
            <span class="token string">'/api'</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
                target<span class="token punctuation">:</span> <span class="token string">'https://baidu.com'</span><span class="token punctuation">,</span>
                secure<span class="token punctuation">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
                pathRewrite<span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token string">'^/api'</span><span class="token punctuation">:</span> <span class="token string">''</span><span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">又有新的需求了，这时候只能代理<code>json</code>接口的数据，对于<code>html</code>文件，还是使用打包后 dist 文件夹中文件，那么我们使用<code>bypass</code>来实现这个需求：</p>
</div><div class="cl-preview-section"><pre class="  language-js"><code class="prism  language-js">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token comment">//...</span>
    devServer<span class="token punctuation">:</span> <span class="token punctuation">{</span>
        proxy<span class="token punctuation">:</span> <span class="token punctuation">{</span>
            <span class="token string">'/api'</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
                target<span class="token punctuation">:</span> <span class="token string">'http://baidu.com'</span><span class="token punctuation">,</span>
                <span class="token function">bypass</span><span class="token punctuation">(</span>req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> proxyOptions<span class="token punctuation">)</span> <span class="token punctuation">{</span>
                    <span class="token comment">// 判断请求头中的 accept 值</span>
                    <span class="token keyword">if</span> <span class="token punctuation">(</span>req<span class="token punctuation">.</span>headers<span class="token punctuation">.</span>accept<span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span><span class="token string">'html'</span><span class="token punctuation">)</span> <span class="token operator">!==</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Skipping proxy for browser request.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                        <span class="token comment">// 返回的是 contentBase 的路径</span>
                        <span class="token keyword">return</span> <span class="token string">'/index.html'</span><span class="token punctuation">;</span>
                    <span class="token punctuation">}</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">或者，我们需要代理<code>http://baidu.com</code>下面的<code>/api</code>和<code>/auth</code>两个地址，其他的地址都放行，这时候可以使用<code>context</code>：</p>
</div><div class="cl-preview-section"><pre class="  language-js"><code class="prism  language-js">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token comment">//...</span>
    devServer<span class="token punctuation">:</span> <span class="token punctuation">{</span>
        proxy<span class="token punctuation">:</span> <span class="token punctuation">[</span>
            <span class="token punctuation">{</span>
                context<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">'/auth'</span><span class="token punctuation">,</span> <span class="token string">'/api'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
                target<span class="token punctuation">:</span> <span class="token string">'http://baidu.com'</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">]</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">原理上来说，webpack-dev-server 使用了 <a href="https://github.com/chimurai/http-proxy-middleware">http-proxy-middleware</a>中间件来实现的 proxy 功能，所以更多配置项及其实现可以直接参考 <a href="https://github.com/chimurai/http-proxy-middleware">http-proxy-middleware</a>的文档</p>
</div><div class="cl-preview-section"><h2 id="自定义中间件" style="font-size: 30px;">自定义中间件</h2>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">在 webpack-dev-server 中有两个时机可以插入自己实现的中间件，分别是在<code>devServer.before</code>和<code>devServer.after</code>两个时机，即 webpack-dev-server 加载所有内部中间件之前和之后两个时机。</p>
</div><div class="cl-preview-section"><pre class="  language-js"><code class="prism  language-js">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token comment">//...</span>
    devServer<span class="token punctuation">:</span> <span class="token punctuation">{</span>
        <span class="token function">before</span><span class="token punctuation">(</span>app<span class="token punctuation">,</span> server<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            app<span class="token punctuation">.</span><span class="token keyword">get</span><span class="token punctuation">(</span><span class="token string">'/some/path'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>req<span class="token punctuation">,</span> res<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
                res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">{</span>custom<span class="token punctuation">:</span> <span class="token string">'response'</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">自定义中间件在开发中常常被用来做 mock server 使用。</p>
</div><div class="cl-preview-section"><h2 id="mock-server" style="font-size: 30px;">mock server</h2>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">现在的前端团队一般都会采取前后端分离的开发模式，这样可以做到前后端同时并行开发，而前端同学开发的时候需要依赖后端同学提供的数据接口，后端同学的数据接口没有开发完成的时候，前端不能傻傻得等着，所以这就需要一个 mock server 来根据前后端接口的约定格式伪造一些假数据，这样前端开发就可以继续下去，加快开发进度。</p>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">webpack-dev-server 提供了自定义中间件的 Hook，所以我们可以很简单的实现自己的 mock server。下面代码是在<code>devServer.before</code>插入一个接口<code>/api/mock.json</code>的接口响应：</p>
</div><div class="cl-preview-section"><pre class="  language-js"><code class="prism  language-js">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token comment">//...</span>
    devServer<span class="token punctuation">:</span> <span class="token punctuation">{</span>
        port<span class="token punctuation">:</span> <span class="token number">9000</span><span class="token punctuation">,</span>
        <span class="token function">before</span><span class="token punctuation">(</span>app<span class="token punctuation">,</span> server<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            app<span class="token punctuation">.</span><span class="token keyword">get</span><span class="token punctuation">(</span><span class="token string">'/api/mock.json'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>req<span class="token punctuation">,</span> res<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
                res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">{</span>hello<span class="token punctuation">:</span> <span class="token string">'world'</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">启动 dev server，访问 <a href="http://localhost:9000/api/mock.json">http://localhost:9000/api/mock.json</a>就可以看到这个接口返回的数据了。</p>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;"><a href="https://juejin.im/post/5afba2746fb9a07aaf356327">https://juejin.im/post/5afba2746fb9a07aaf356327</a></p>
</div><div class="cl-preview-section"><ul>
<li style="font-size: 20px; line-height: 38px;">
<h2 id="devserver.compress：服务开启-gzip-压缩；" style="font-size: 30px;"><code>devServer.compress</code>：服务开启 Gzip 压缩；</h2>
</li>
</ul>
</div><div class="cl-preview-section"><blockquote>
<p style="font-size: 20px; line-height: 38px;">Tips：<code>devServer.setup</code>也可以用于设置 mock server，但是已经被废弃了，将来版本肯定会被删除，不过使用<code>devServer.before</code>和<code>devServer.after</code>这俩 Hook 已经够用了。</p>
</blockquote>
</div><div class="cl-preview-section"><h2 id="webpack-dev-server-常用配置" style="font-size: 30px;">Webpack Dev Server 常用配置</h2>
</div><div class="cl-preview-section"><ul>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.historyApiFallback</code>：配置如果找不到页面就默认显示的页面；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.compress</code>：启用 gzip 压缩；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.hotOnly</code>：构建失败的时候是否不允许回退到使用刷新网页；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.inline</code>：模式切换，默认为内联模式，使用<code>false</code>切换到 iframe 模式；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.open</code>：启动后，是否自动使用浏览器打开首页；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.openPage</code>：启动后，自动使用浏览器打开设置的页面；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.overlay</code>：是否允许使用全屏覆盖的方式显示编译错误，默认不允许；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.port</code>：监听端口号，默认 8080；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.host</code>：指定 host，使用<code>0.0.0.0</code>可以让局域网内可访问；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.contentBase</code>：告诉服务器从哪里提供内容，只有在你想要提供静态文件时才需要；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.publicPath</code>：设置内存中的打包文件的虚拟路径映射，区别于<code>output.publicPath</code>；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.staticOptions</code>：为 Expressjs 的 <code>express.static</code>配置参数，参考文档： <a href="http://expressjs.com/en/4x/api.html#express.static">http://expressjs.com/en/4x/api.html#express.static</a></li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.clientLogLevel</code>：在 inline 模式下用于控制在浏览器中打印的 log 级别，如<code>error</code>, <code>warning</code>, <code>info</code> or <code>none</code>；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.quiet</code>：静默模式，设置为<code>true</code>则不在控制台输出 log；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.noInfo</code>：不输出启动 log；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.lazy</code>: 不监听文件变化，而是当请求来的时候再重新编译；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.watchOptions</code>：watch 相关配置，可以用于控制间隔多少秒检测文件的变化；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.headers</code>：自定义请求头，例如自定义 userAgent 等；</li>
<li style="font-size: 20px; line-height: 38px;"><code>devServer.https</code>：https 需要的证书签名等配置。</li>
</ul>
</div><div class="cl-preview-section"><h2 id="title小结---" style="font-size: 30px;"><div class="summary"><h5 class="centertitle" style="font-size: 20px; line-height: 38px;">小结 </h5></div><!--title:&#23567;&#32467; --></h2>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">Webpack 的 webpack-dev-server 是 Webpack 生态链上很重要的一环，在我们日常的开发环境，我们可以使用 webpack-dev-server 启动本地服务器，而且能够实现 API 接口代理、静态资源服务器、HMR，甚至还能够通过编写 Express 中间件的方式来扩展功能。</p>
</div><div class="cl-preview-section"><p style="font-size: 20px; line-height: 38px;">但是 webpack-dev-server 本身也有它的局限性，比如我们项目本身就有一个 Node.js 的业务服务，那么在使用 webpack-dev-server 来模拟接口数据就显得多此一举了。后面实战章节我们将介绍使用 Express 的中间件来实现一个自己的 dev-server！</p>
</div><div class="cl-preview-section"><blockquote>
<p style="font-size: 20px; line-height: 38px;">本小节 Webpack 相关面试题：</p>
<ol>
<li style="font-size: 20px; line-height: 38px;">webpack-dev-server 的 inline 模式和 iframe 模式有何异同？</li>
<li style="font-size: 20px; line-height: 38px;">webpack-dev-server 怎么配置 HMR？</li>
<li style="font-size: 20px; line-height: 38px;">webpack-dev-server 怎么使用 Express 中间件？</li>
<li style="font-size: 20px; line-height: 38px;">能够说下你对 webpack-dev-server 理解吗？原理吗？</li>
</ol>
</blockquote>
</div></div>
            </div>
                            <!-- 买过的阅读 -->
                <div class="art-next-prev clearfix">
                                                                        <!-- 已买且开放 或者可以试读 -->
                            <a href="http://www.itjc8.com">
                                                    <div class="prev l clearfix">
                                <div class="icon l">
                                    <i class="imv2-arrow3_l"></i>
                                </div>
                                <p>
                                    13 Webpack 中打包 HTML 和多页面配置
                                </p>
                            </div>
                        </a>
                                                                                            <!-- 已买且开放 或者可以试读 -->
                            <a href="/read/29/article/273">
                                                    <div class="next r clearfix">
                                <p>
                                    15 Webpack 中配置React和Vue开发环境
                                </p>
                                <div class="icon r">
                                    <i class="imv2-arrow3_r"></i>
                                </div>

                            </div>
                        </a>
                                    </div>
                    </div>
        <div class="comments-con js-comments-con" id="coments_con">
        </div>



    </div>
    
    
    

</div>
 
<!-- 专栏介绍页专栏评价 -->

<!-- 专栏介绍页底部三条评价 -->

<!-- 专栏阅读页弹层目录和介绍页页面目录 -->

<!-- 专栏阅读页发布回复 -->

<!-- 专栏阅读页发布评论 -->

<!-- 专栏阅读页底部评论 -->

<!-- 专栏阅读 单个 评论 -->

<!-- 新增回复和展开三条以外回复 -->

<!-- 立即订阅的弹窗 -->












</div></body></html>